package io.gitee.kenewstar.dbmq;

import io.gitee.kenewstar.dbmq.data.DbDataHandler;
import io.gitee.kenewstar.dbmq.data.DbDataHandlerAdapter;
import io.gitee.kenewstar.dbmq.data.DbDataHandlerWrapper;
import io.gitee.kenewstar.dbmq.data.DbMySqlHandler;
import io.gitee.kenewstar.dbmq.handler.DbMqAssembleHandler;
import io.gitee.kenewstar.dbmq.handler.DbMqConsumerTaskHandler;
import io.gitee.kenewstar.dbmq.handler.PullMessageHandler;
import io.gitee.kenewstar.dbmq.thread.DbMqConsumerThreadPool;
import io.gitee.kenewstar.dbmq.thread.WorkThreadPool;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@AutoConfigureOrder(Integer.MAX_VALUE)
@Service
@Configuration
@EnableConfigurationProperties(DbMqConfigProperties.class)
public class DbMqConfig {

    @Resource
    private DbMqConfigProperties dbMqConfigProperties;

    @Bean
    public DbMqAssembleHandler dbMqAssembleHandler(List<DbMqConsumerInf> infList,
                                                   DbDataHandler dbDataHandler,
                                                   DbMqConfigProperties dbMqConfigProperties,
                                                   DbMqConsumerTaskHandler dbMqConsumerTaskHandler,
                                                   PullMessageHandler pullMessageHandler) {
        return new DbMqAssembleHandler(infList, dbDataHandler, dbMqConfigProperties, dbMqConsumerTaskHandler, pullMessageHandler);
    }

    @Bean
    public DbMqMessageProducer messageProducer(DbDataHandler dbDataHandler,
                                               DbMqConfigProperties dbMqConfigProperties) {
        return new DbMqMessageProducer(dbDataHandler, dbMqConfigProperties);
    }

    @Bean
    public DbMqConsumerTaskHandler dbMqConsumerTaskHandler(DbMqConfigProperties dbMqConfigProperties,
                                                           DbMqConsumerThreadPool dbMqConsumerThreadPool,
                                                           PullMessageHandler pullMessageHandler) {
        return new DbMqConsumerTaskHandler(dbMqConfigProperties, dbMqConsumerThreadPool, pullMessageHandler);
    }

    @Bean
    public PullMessageHandler pullMessageHandler(DbDataHandler dbDataHandler,
                                                 DbMqConfigProperties dbMqConfigProperties,
                                                 WorkThreadPool workThreadPool) {
        return new PullMessageHandler(dbDataHandler, dbMqConfigProperties, workThreadPool);
    }

    @Bean
    public DbMqConsumerThreadPool dbMqConsumerThreadPool(WorkThreadPool workThreadPool) {
        return new DbMqConsumerThreadPool(workThreadPool);
    }

    @Bean
    public WorkThreadPool workThreadPool(DbDataHandler dbDataHandler) {
        return new WorkThreadPool(dbDataHandler);
    }


    @Bean
    public DbDataHandler dbDataHandler(DbDataHandlerWrapper dbDataHandlerWrapper) {
        return dbDataHandlerWrapper.toHandler(this.dbMqConfigProperties.getType());
    }


    @Bean
    public DbDataHandlerWrapper dbDataHandlerWrapper(List<DbDataHandlerAdapter> list) {
        List<DbDataHandler> handlerList = list.stream().map(DbDataHandlerAdapter::adapter).collect(Collectors.toList());
        return new DbDataHandlerWrapper(handlerList);
    }


    @Bean
    @ConditionalOnBean(DataSource.class)
    public DbMySqlHandler dbMySqlHandler(DataSource dataSource) {
        return new DbMySqlHandler(dataSource);
    }

}
